﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Svg;
using System.Drawing;
using System.ComponentModel;
using System.Runtime.Serialization;
using Commons.Enums;
using System.IO;
using System.Xml;
using Commons;
using Svg.Transforms;
using Svg.Pathing;
using HumanFace.Common;
using CsPotrace;

namespace HumanFace
{
    [DataContract]
    public class Face : Entities.Base.FaceBASE
    {
        public Face(NodeCollection pointList, Dictionary<string, string> templates, string imagePath)
            : base(templates,pointList)
        {  
            this.ImagePath = imagePath;
            CreateOrgans();
            CreateProperties();
            RenderVectorelGraphic();
          
        }
        

        public Face()
        {

        }
        private void CreateProperties()
        {
            #region MostLeftPoint
            Node nd0 = PointList["0"];
            this.MostLeftPoint = nd0;
            #endregion
            #region MostTopPoint
            NodeCollection probTop = new NodeCollection();
            probTop.Add(PointList["16"]);
            probTop.Add(PointList["17"]);
            probTop.Add(PointList["22"]);
            probTop.Add(PointList["23"]);

            this.MostTopPoint = probTop[0];
            foreach (Node item in probTop)
            {
                if (item.Y < this.MostTopPoint.Y)
                    this.MostTopPoint = item;
            }
            #endregion
        }
        private void CreateOrgans()
        {
            
            // Left Eye : 27-31 , 68-71
            NodeCollection leftEyeList = new NodeCollection();
            AddnewPointsToList(leftEyeList, 27, 31);
            AddnewPointsToList(leftEyeList, 68, 71);
            leftEyeList.Add(this.PointList["26"]);
            leftEyeList.Add(this.PointList["21"]);
            leftEyeList.Add(this.PointList["37"]);
            this.LeftEye = new Eye(leftEyeList, Direction.LEFT ,this.Templates);

            // Right Eye : 32-36 , 72-75
            NodeCollection rightEyeList = new NodeCollection();
            AddnewPointsToList(rightEyeList, 32, 36);
            AddnewPointsToList(rightEyeList, 72, 75);
            rightEyeList.Add(this.PointList["20"]);
            rightEyeList.Add(this.PointList["45"]);
            rightEyeList.Add(this.PointList["15"]);
            this.RightEye = new Eye(rightEyeList, Direction.RIGHT, this.Templates);
            

            // Left Eyebrow : 21-26
            NodeCollection leftEyeBrowList = new NodeCollection();
            AddnewPointsToList(leftEyeBrowList, 21, 26);
            this.LeftEyeBrow = new EyeBrow(leftEyeBrowList, Convert.ToInt16(Direction.LEFT), this.Templates);

            // Right Eyebrow : 15-20
            NodeCollection rightEyeBrowList = new NodeCollection();
            AddnewPointsToList(rightEyeBrowList, 15, 20);
            this.RightEyeBrow = new EyeBrow(rightEyeBrowList, Convert.ToInt16(Direction.RIGHT), this.Templates);

            // Lips : 48-66
            NodeCollection lipsList = new NodeCollection();
            AddnewPointsToList(lipsList, 48, 66);
            this.Lips = new Lips(lipsList, this.Templates);

            // Nose : 37-47, 67
            NodeCollection noseList = new NodeCollection();
            AddnewPointsToList(noseList, 37, 47);
            noseList.Add(this.PointList["67"]);
            this.Nose = new Nose(noseList, this.Templates);

            // Visage : 0-14
            NodeCollection visageList = new NodeCollection();
            AddnewPointsToList(visageList, 0, 14);
            this.Visage = new Visage(visageList, this.Templates);
        
        }

        private void ChangePoints()
        {
            SvgDocument templateFace = SvgDocument.Open("c:\\template.svg");

            SvgElement visage = templateFace.GetElementById("visage");
            SvgElement eyebrow_left = templateFace.GetElementById("eyebrow_left");
            SvgElement eye_left = templateFace.GetElementById("eye_left");
            SvgElement nose = templateFace.GetElementById("nose");
            SvgElement lips_out = templateFace.GetElementById("lips_out");
            SvgElement nose_right = templateFace.GetElementById("nose_right");
            SvgElement pupil_left = templateFace.GetElementById("pupil_left");
            SvgElement lips_in = templateFace.GetElementById("lips_in");
            SvgElement nose_left = templateFace.GetElementById("nose_left");
            SvgElement eye_right = templateFace.GetElementById("eye_right");
            SvgElement pupil_right = templateFace.GetElementById("pupil_right");
            SvgElement eyebrow_right = templateFace.GetElementById("eyebrow_right");

            for (int v = 0; v < ((Svg.SvgPath)(visage)).PathData.Count; v++)
            {
                System.Drawing.PointF pntsS = ((Svg.SvgPath)(visage)).PathData[v].Start;
                System.Drawing.PointF pntsF = ((Svg.SvgPath)(visage)).PathData[v].End;

            }


        }

        private void AddnewPointsToList(NodeCollection pList, int left, int right)
        {
            for (int i = left; i <= right; i++)
            {
                pList.Add(this.PointList[i.ToString()]);
            }
        }

        protected override void RenderVectorelGraphic()
        { 
            base.RenderVectorelGraphic();
            CsPotraceEngine eng = new CsPotraceEngine();
            Bitmap bm = new Bitmap(this.ImagePath);
            SvgGroup quantizedFace = eng.trace(bm);
            quantizedFace.ID = "quantizedFace";
            this.SVG.Children.Add(quantizedFace);
           
            LocateOrgan(this.RightEye);
            LocateOrgan(this.LeftEye);
            LocateOrgan(this.Nose);
            LocateOrgan(this.Lips);

            
            //Test();
            SvgDocument doc = new SvgDocument();
            if (this.SVG != null)
            {

                SvgGroup svgGr = new SvgGroup();
                foreach (SvgElement  item in this.SVG.Children)
                {
                    if (!String.IsNullOrEmpty(item.ID) && item.ID == "quantizedFace")
                    {
                        doc.Children.Add(item);
                    }
                    if (!String.IsNullOrEmpty(item.ID) && item.ID != "quantizedFace")
                    {
                        svgGr.Children.Add(item);
                    }
                }


                SvgTransformCollection transformCollection = new SvgTransformCollection();
                if (svgGr.Transforms != null) transformCollection = svgGr.Transforms;
                SketchHelper.Translate(this.MostLeftPoint.X-4, this.MostTopPoint.Y-3, transformCollection);
                svgGr.Transforms = transformCollection;


                doc.Children.Add(svgGr);
                this.SVG = doc;
                this.SvgDoc = SketchHelper.ConvertTo(this.SVG);
            }

            
        }
        private void LocateOrgan(Organ organ)
        {
            if (organ != null && organ.SVG != null)
            {
                SvgTransformCollection transformCollection = new SvgTransformCollection();
                if (organ.SVG.Transforms != null) transformCollection = organ.SVG.Transforms;
                SketchHelper.Translate(organ.MostLeftPoint.X - this.MostLeftPoint.X, organ.MostTopPoint.Y - this.MostTopPoint.Y, transformCollection);
                organ.SVG.Transforms = transformCollection;

                this.SVG.Children.Add(RemoveSvgTags(organ.SVG));
            }
        }
        private SvgGroup RemoveSvgTags(SvgDocument svg)
        {
            SvgGroup retVal = null;
            if (svg != null && svg.Children != null && svg.Children.Count > 0)
            {
                retVal = new SvgGroup();
                //Diğer Propertyler gerçilmeli mi ?
                retVal.ID = svg.ID;
                retVal.Content = svg.Content;
                retVal.Transforms = svg.Transforms;
                foreach (SvgElement item in svg.Children)
                {
                    retVal.Children.Add(item);
                }
            }

            return retVal;
        }
    }
}
